package com.weilive.core.utils;

import java.net.URLDecoder;
import java.nio.charset.Charset;

public class QueryStringDecoder extends PropertiesMap {
	
	private final String path;

	public QueryStringDecoder(String uri) throws Exception {
		this(uri, StringUtils.DEFAULT_CHARSET);
	}
	
	public QueryStringDecoder(String uri, Charset charset) throws Exception {
		// http://en.wikipedia.org/wiki/Query_string
		uri = URLDecoder.decode(uri.replace(';', '&'), charset.name());
		int paramsStartPos = uri.indexOf('?');
		if (paramsStartPos < 0) {
			path = uri;
			paramsStartPos = 0;
		} else {
			path = uri.substring(0, paramsStartPos);
			paramsStartPos++;
		}
		if (paramsStartPos == path.length()) {
		} else {
			decodeParams(uri.substring(paramsStartPos));
		}
	}
	
	public QueryStringDecoder(String path, String content) throws Exception {
		this(path, content, StringUtils.DEFAULT_CHARSET);
	}
	
	public QueryStringDecoder(String path, String content, Charset charset) throws Exception {
		this.path = path;
		
		if (content.length() == 0) {
		} else {
			content = URLDecoder.decode(content.replace(';', '&'), charset.name());
			decodeParams(content);
		}
	}
	
	private void decodeParams(String s) {
		String name = null;
		int pos = 0; // Beginning of the unprocessed region
		int i;       // End of the unprocessed region
		char c;      // Current character
		for (i = 0; i < s.length(); i++) {
			c = s.charAt(i);
			if (c == '=' && name == null) {
				if (pos != i) {
					name = s.substring(pos, i);
				}
				pos = i + 1;
			} else if (c == '&') {
				if (name == null && pos != i) {
					// We haven't seen an `=' so far but moved forward.
					// Must be a param of the form '&a&' so add it with
					// an empty value.
					properties.put(s.substring(pos, i), "");
				} else if (name != null) {
					properties.put(name, s.substring(pos, i));
					name = null;
				}
				pos = i + 1;
			}
		}

		if (pos != i) {  // Are there characters we haven't dealt with?
			if (name == null) {     // Yes and we haven't seen any `='.
				properties.put(s.substring(pos, i), "");
			} else {                // Yes and this must be the last value.
				properties.put(name, s.substring(pos, i));
			}
		} else if (name != null) {  // Have we seen a name without value?
			properties.put(name, "");
		}
	}

	public String getPath() {
		return path;
	}

	public void remove(String key) {
		properties.remove(key);
	}
}
